package com.wanmait.teatrain.service.impl;

import ai.z.openapi.ZhipuAiClient;
import ai.z.openapi.service.model.ChatCompletionCreateParams;
import ai.z.openapi.service.model.ChatCompletionResponse;
import ai.z.openapi.service.model.ChatMessage;
import ai.z.openapi.service.model.ChatMessageRole;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wanmait.teatrain.dto.utils.AIScoreResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class AIScoringService {


    @Value("${zhipuai.api.key:}")
    private String apiKey;

    private static final double CORRECT_THRESHOLD = 0.6;
    /**
     * 使用智谱AI进行简答题评分
     */
    public AIScoreResult scoreShortAnswer(String userAnswer, String standardAnswer,
                                          String keywords, Integer fullScore) {
        try {
            // 1. 构建评分提示词
            String prompt = buildScoringPrompt(userAnswer, standardAnswer, keywords, fullScore);

            // 2. 调用智谱AI API
            ChatCompletionResponse response = callZhipuAI(prompt);

            // 3. 解析AI返回结果
            return parseAIResponse(response, fullScore);

        } catch (Exception e) {
            // AI服务失败时降级到本地算法
            return fallbackScoring(userAnswer, standardAnswer, keywords, fullScore);
        }
    }

    /**
     * 构建评分提示词
     */
    private String buildScoringPrompt(String userAnswer, String standardAnswer,
                                      String keywords, Integer fullScore) {
        return String.format(
                "你是一个专业的考试评分AI助手。请对以下简答题答案进行评分：\n\n" +
                        "【标准答案】\n%s\n\n" +
                        "【关键词】\n%s\n\n" +
                        "【学生答案】\n%s\n\n" +
                        "【评分要求】\n" +
                        "1. 从内容准确性、关键词覆盖、逻辑完整性、语言表达四个维度评分\n" +
                        "2. 总分：%d分\n" +
                        "3. 请严格返回JSON格式：{\"score\": 得分, \"similarity\": 相似度0-1, \"isCorrect\": 布尔值, \"feedback\": \"评分理由\"}\n" +
                        "4. 相似度>=%.2f时isCorrect为true\n" +
                        "5. 评分理由要具体说明得分点和扣分点\n" +
                        "6. 得分不能超过总分，相似度在0-1之间\n\n" +
                        "请直接返回JSON，不要其他任何内容：",
                standardAnswer, keywords, userAnswer, fullScore, CORRECT_THRESHOLD
        );
    }

    /**
     * 调用智谱AI API
     */
    private ChatCompletionResponse callZhipuAI(String prompt) {
        // 初始化客户端
        ZhipuAiClient client = ZhipuAiClient.builder()
                .apiKey(apiKey)
                .build();

        // 创建聊天完成请求
        ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
                .model("glm-4")  // 使用GLM-4模型，根据实际情况调整
                .messages(Arrays.asList(
                        ChatMessage.builder()
                                .role(ChatMessageRole.USER.value())
                                .content(prompt)
                                .build()
                ))
                .stream(false)
                .temperature(0.1f)  // 低随机性保证评分一致性
                .maxTokens(1024)
                .build();

        // 发送请求并返回响应
        return client.chat().createChatCompletion(request);
    }

    /**
     * 解析AI响应
     */
    private AIScoreResult parseAIResponse(ChatCompletionResponse response, Integer fullScore) {
        try {
            String content = (String) response.getData().getChoices().get(0).getMessage().getContent();

            // 清理响应内容，确保是纯JSON
            content = content.trim();
            if (content.startsWith("```json")) {
                content = content.substring(7);
            }
            if (content.endsWith("```")) {
                content = content.substring(0, content.length() - 3);
            }
            content = content.trim();

            // 解析JSON响应
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> result = mapper.readValue(content, Map.class);

            double score = ((Number) result.get("score")).doubleValue();
            double similarity = ((Number) result.get("similarity")).doubleValue();
            boolean isCorrect = (Boolean) result.get("isCorrect");
            String feedback = (String) result.get("feedback");

            // 确保分数不超过满分且不为负
            score = Math.max(0, Math.min(score, fullScore));
            similarity = Math.max(0, Math.min(similarity, 1.0));

            return new AIScoreResult(score, similarity, isCorrect, feedback);

        } catch (Exception e) {
            throw new RuntimeException("解析AI响应失败: " + e.getMessage(), e);
        }
    }

    /**
     * AI服务降级方案 - 本地算法
     */
    private AIScoreResult fallbackScoring(String userAnswer, String standardAnswer,
                                          String keywords, Integer fullScore) {
        System.out.println("AI评分服务失败，使用降级本地算法");

        double similarity = calculateLocalSimilarity(userAnswer, standardAnswer, keywords);
        double score = similarity * fullScore;
        boolean isCorrect = similarity >= CORRECT_THRESHOLD;

        String feedback = String.format("本地算法评分：相似度%.2f，得分%.1f/%d",
                similarity, score, fullScore);

        return new AIScoreResult(score, similarity, isCorrect, feedback);
    }

    /**
     * 本地相似度计算（降级方案）
     */
    private double calculateLocalSimilarity(String userAnswer, String standardAnswer, String keywords) {
        double keywordScore = calculateKeywordMatch(userAnswer, keywords);
        double semanticScore = calculateTextSimilarity(userAnswer, standardAnswer);

        // 综合评分
        return (keywordScore * 0.4 + semanticScore * 0.6);
    }

    private double calculateKeywordMatch(String userAnswer, String keywords) {
        if (keywords == null || keywords.trim().isEmpty()) return 1.0;

        String[] keywordArray = keywords.split(",");
        int matched = 0;
        for (String keyword : keywordArray) {
            String cleanKeyword = keyword.trim().toLowerCase();
            if (!cleanKeyword.isEmpty() && userAnswer.toLowerCase().contains(cleanKeyword)) {
                matched++;
            }
        }
        return keywordArray.length > 0 ? (double) matched / keywordArray.length : 1.0;
    }

    private double calculateTextSimilarity(String text1, String text2) {
        if (text1 == null || text2 == null) return 0.0;

        Set<String> words1 = new HashSet<>(Arrays.asList(text1.toLowerCase().split("\\s+")));
        Set<String> words2 = new HashSet<>(Arrays.asList(text2.toLowerCase().split("\\s+")));

        Set<String> intersection = new HashSet<>(words1);
        intersection.retainAll(words2);

        Set<String> union = new HashSet<>(words1);
        union.addAll(words2);

        return union.isEmpty() ? 0.0 : (double) intersection.size() / union.size();
    }
}

